package de.clue.corpus.twitter;

import java.util.Vector;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

import de.clue.corpus.twitter.build.CreateByQueryTwitterCorpus;
import de.clue.corpus.twitter.build.CreateTwitterCorpus;
import de.clue.corpus.twitter.langident.SaxFileReader;
import de.clue.corpus.twitter.reader.DuplicateElementAppender;
import de.clue.corpus.twitter.reader.EmoticonPolarityElementAppender;
import de.clue.corpus.twitter.reader.EscapeDoubleQuotesTextWorker;
import de.clue.corpus.twitter.reader.GenericSaxFileReader;
import de.clue.corpus.twitter.reader.IElementAppender;
import de.clue.corpus.twitter.reader.ITextWorker;
import de.clue.corpus.twitter.reader.RemoveEmoticonsTextWorker;
import de.clue.corpus.twitter.reader.RemoveReTweetTextWorker;
import de.clue.corpus.twitter.reader.RemoveTwitterHashTagTextWorker;
import de.clue.corpus.twitter.reader.ReplaceLinkTextWorker;
import de.clue.corpus.twitter.reader.ReplaceTwitterUsernameTextWorker;
import de.clue.corpus.twitter.transform.XalanTransformDirectory;
import de.clue.corpus.twitter.treetagger.TreeTagger;
import de.clue.corpus.twitter.validate.Validator;


/**
 * 
 * Main class for execution
 * 
 * @author asuslova
 * @author sboehme
 *
 */
public class TwitterCorpus {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		// create the parser
		CommandLineParser parser = new GnuParser();
//		CommandLineParser parser = new PosixParser();

		Options options = getOptions();
		
	    try {
	        // parse the command line arguments
			CommandLine line = parser.parse( options, args );
			
			// Find out what to do
		    if( line.getOptions().length > 0 ) {
		    	boolean commandFound = false;
		    	
		    	// show help --------------------------------------------------
		    	if(line.hasOption("help")){
		    		usage(new HelpFormatter(), options, 0);
		    		commandFound = true;
		    	}
		    	
		    	// show <man>ual ----------------------------------------------
		    	if(line.hasOption("man")){
		    		System.out.println("TODO");
		    		commandFound = true;
		    	}
		    	
		    	// Create corpus ----------------------------------------------
		    	if(line.hasOption(TwitterCorpusConstants.COMMANDLINE_CORPUS)){
		    		cmdCreateCorpus(options, line);
		    		commandFound = true;
		    		
		    	}
		    	
		    	// query twitter to create corpus ----------------------------------------------
		    	if(line.hasOption(TwitterCorpusConstants.COMMANDLINE_QUERYTWITTER)){
		    	    cmdCreateCorpusByQuery(options, line);
		    	    commandFound = true;
		    	    
		    	}
		    	
		    	// Stop creating corpus ---------------------------------------
		    	if(line.hasOption(TwitterCorpusConstants.COMMANDLINE_CORPUS_STOP)){
		    		cmdStopCorpus(options, line);
		    		commandFound = true;
		    		
		    	}
		    	
		    	// Identify language ------------------------------------------
		    	if(line.hasOption(TwitterCorpusConstants.COMMANDLINE_LANGID)){
		    		cmdLanguageIdentification(options,line);
		    		commandFound = true;
		    	}
		    	
		    	// Validate and repair ----------------------------------------
		    	if(line.hasOption(TwitterCorpusConstants.COMMANDLINE_VALIDATION)){
		    		cmdValidateFiles(options,line);
		    		commandFound = true;
		    	}
		    	
		    	
		    	// Tag the corpus files ---------------------------------------
		    	if(line.hasOption(TwitterCorpusConstants.COMMANDLINE_TAG)){
		    		cmdTagFiles(options,line);
		    		commandFound = true;
		    	}
		    	
		    	
		    	// Find polarity in the corpus files --------------------------
		    	if(line.hasOption(TwitterCorpusConstants.COMMANDLINE_POLARITY)){
		    	    cmdPolarityFiles(options,line);
		    	    commandFound = true;
		    	}
		    	
		    	// Find transform in the corpus files --------------------------
		    	if(line.hasOption(TwitterCorpusConstants.COMMANDLINE_TRANSFORM)){
		    	    cmdTransformFiles(options,line);
		    	    commandFound = true;
		    	}
		    	
		    	
		    	
		    	// nothing to do that's an error!------------------------------
		    	if(!commandFound){
		    		usage(new HelpFormatter(), options, 1);
		    	}
		       
		    	
		    } else {
		    	// no argument provided
		    	// automatically generate the help statement and exit
		    	usage(new HelpFormatter(), options, 0);
		    	
		    }
			
	    } catch( ParseException exp ) {
	        // oops, something went wrong
	        System.err.println( "Parsing failed.  Reason: " + exp.getMessage() );
	        usage(new HelpFormatter(), options, 0);
	        
	    }

	}




	private static void cmdTransformFiles(Options options, CommandLine line) {
	    System.out.println("Transform files");

        // xsl
        String xslFile = line.getOptionValue(TwitterCorpusConstants.COMMANDLINE_XSL);
        if(xslFile == null){
            TwitterCorpus.usage(new HelpFormatter(), options, 1);
        }
        System.out.println("XSL:\t\t" + xslFile);
        // path
        String path = line.getOptionValue(TwitterCorpusConstants.COMMANDLINE_PATH);
        if(path == null){
            TwitterCorpus.usage(new HelpFormatter(), options, 1);
        }
        System.out.println("Path:\t\t" + path);
        // outputpath
        String outputpath = line.getOptionValue(TwitterCorpusConstants.COMMANDLINE_OUTPUTPATH);
        if(outputpath == null){
            TwitterCorpus.usage(new HelpFormatter(), options, 1);
        }
        System.out.println("OutputPath:\t\t" + outputpath);
        
        // start of transformation
        try {
            
            XalanTransformDirectory xalanTransformDirectory = new XalanTransformDirectory(path, outputpath, xslFile);
            xalanTransformDirectory.process();
            
            
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
            
        }
        
    }




    private static void cmdPolarityFiles(Options options, CommandLine line) {
        
	    System.out.println("Polarity Identifier");

        // path
        String path = line.getOptionValue(TwitterCorpusConstants.COMMANDLINE_PATH);
        if(path == null){
            TwitterCorpus.usage(new HelpFormatter(), options, 1);
        }
        System.out.println("Path:\t\t" + path);
        // outputpath
        String outputpath = line.getOptionValue(TwitterCorpusConstants.COMMANDLINE_OUTPUTPATH);
        if(outputpath == null){
            TwitterCorpus.usage(new HelpFormatter(), options, 1);
        }
        System.out.println("OutputPath:\t\t" + outputpath);
        
        // start of polarity
        try {
            Vector<ITextWorker> workers = new Vector<ITextWorker>();
            Vector<IElementAppender> appender = new Vector<IElementAppender>();
            // todo get from command line oder properties
            appender.add(new EmoticonPolarityElementAppender()); // add polarity
            appender.add(new DuplicateElementAppender()); // check for duplicates
            
            workers.add(new EscapeDoubleQuotesTextWorker()); // escape double quotes for weka
            workers.add(new RemoveReTweetTextWorker()); // first remove retweet
            workers.add(new ReplaceTwitterUsernameTextWorker()); // then replace @name with BENUTZERNAME
            workers.add(new RemoveTwitterHashTagTextWorker()); // then remove hash tag #
            workers.add(new ReplaceLinkTextWorker()); // then replace urls with URLLINK
            workers.add(new RemoveEmoticonsTextWorker()); // then remove emoticons 
            
            GenericSaxFileReader genericSaxFileReader = new GenericSaxFileReader(path, outputpath, workers , appender );
            genericSaxFileReader.process();
            
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
            
        }
        
        
    }




    private static Options getOptions() {
		Options options = new Options();
		
		Option help = new Option( "help", "print this message" );
		options.addOption( help );
		
		Option man = new Option( "man", "print extended help" );
		options.addOption( man );
		
		// Create Corpus -----------------------------------------------------------------------
		Option createcorpus = OptionBuilder
							        .withDescription( "start creating corpus using provided options" )
							        .hasArg(false)
							        .create(TwitterCorpusConstants.COMMANDLINE_CORPUS);
		options.addOption( createcorpus );
		
		Option createcorpusbyquery = OptionBuilder
		        .withDescription( "start creating corpus by query using provided options" )
		        .hasArg(false)
		        .create(TwitterCorpusConstants.COMMANDLINE_QUERYTWITTER);
		options.addOption( createcorpusbyquery );
		
		// Stop creating Corpus -----------------------------------------------------------------
		Option stopcreatecorpus = OptionBuilder
							        .withDescription( "stop creating corpus" )
							        .hasArg(false)
							        .create(TwitterCorpusConstants.COMMANDLINE_CORPUS_STOP);
							options.addOption( stopcreatecorpus );
		
		// Language Id   -----------------------------------------------------------------------
		Option langid = new Option( TwitterCorpusConstants.COMMANDLINE_LANGID, "identify language in existing corpus files" );
		options.addOption( langid );
		
		// Validation    -----------------------------------------------------------------------
		Option validation = new Option( TwitterCorpusConstants.COMMANDLINE_VALIDATION, "validate and repair existing corpus files" );
		options.addOption( validation );
		
		// TreeTagging    -----------------------------------------------------------------------
		Option treetagger = new Option( TwitterCorpusConstants.COMMANDLINE_TAG, "tag the existing corpus files" );
		options.addOption( treetagger );
		
		// Polarity       -----------------------------------------------------------------------
		Option polarity = new Option( TwitterCorpusConstants.COMMANDLINE_POLARITY, "add polarity to existing corpus files" );
		options.addOption( polarity );
		
		// Transform       -----------------------------------------------------------------------
		Option transform = new Option( TwitterCorpusConstants.COMMANDLINE_TRANSFORM, "transform xml files using xsl" );
		options.addOption( transform );
		
		// Date setting for creation of corpus files
		Option filerolling   = OptionBuilder.withArgName( "m|h|d" )
									        .hasArg()
									        .withDescription(  "Change file  <m>inutely, <h>ourly or <d>aily" )
									        .create( TwitterCorpusConstants.COMMANDLINE_CHANGEFILE );
		options.addOption( filerolling );

		
		// Encoding setting for creation of corpus
		Option specialcharacters   = OptionBuilder.withArgName( "esc|cdata" )
								        .hasArg()
								        .withDescription(  "Either <esc>ape special characters or put <cdata> around them" )
								        .create( TwitterCorpusConstants.COMMANDLINE_ESCAPING );
		options.addOption( specialcharacters );
		
		// Path to save the corpus to, to read files from when validating, identify language
		Option path   = OptionBuilder.withArgName( "" )
								        .hasArg()
								        .withDescription(  "Path to use for creation/reading of corpus" )
								        .create( TwitterCorpusConstants.COMMANDLINE_PATH );
		options.addOption( path );

		// query to use for creating corpus
		Option query   = OptionBuilder.withArgName( "" )
		        .hasArg()
		        .withDescription(  "Query to use for creating corpus" )
		        .create( TwitterCorpusConstants.COMMANDLINE_QUERY );
		options.addOption( query );
		
		// Outputpath to save the data to
		Option outputPath   = OptionBuilder.withArgName( "" )
		.hasArg()
		.withDescription(  "Path to use for saving identifed files" )
		.create( TwitterCorpusConstants.COMMANDLINE_OUTPUTPATH );
		options.addOption( outputPath );
		
		// xslPath
		Option xslPath   = OptionBuilder.withArgName( "" )
		        .hasArg()
		        .withDescription(  "Path to the XSL file" )
		        .create( TwitterCorpusConstants.COMMANDLINE_XSL);
		options.addOption( xslPath );
		
		// taggerhome
		Option taggerhome   = OptionBuilder.withArgName( "" )
		.hasArg()
		.withDescription(  "HOME of the tree tagger" )
		.create( TwitterCorpusConstants.CONFIG_TAG_HOME );
		options.addOption( taggerhome );
		
		// model path
		Option modelPath   = OptionBuilder.withArgName( "" )
		.hasArg()
		.withDescription(  "Path and encoding of the language model to use." )
		.create( TwitterCorpusConstants.CONFIG_TAG_MODEL );
		options.addOption( modelPath );
		

		return options;
		
	}

	private static void usage(HelpFormatter formatter, Options options,int exitCode){
		
		formatter.printHelp(
				"TwitterCorpus corpus|langid|validation|treetagger|polarity|transform|querycorpus [CONFIGURATION] -path PATH -outputpath PATH\n" + 
				"Option path is mandatory for all usages!\n" + 
				"Option outputpath is mandatory for some usages!"
				, options );
		
		System.exit(exitCode);
	}
	
	
	private static void cmdCreateCorpus(Options options, CommandLine line) {
		// Get the options needed for creating a corpus
		System.out.println("Creating Corpus Files");
		System.out.println("Options used:");
		
		// changefile
		String changefile = line.getOptionValue(TwitterCorpusConstants.COMMANDLINE_CHANGEFILE);
		if(changefile == null){
			changefile = TwitterCorpusConstants.CONFIG_CHANGEFILE_HOURLY;
		}
		System.out.println("Changing file:\t" + changefile);
		
		// escaping
		String escaping = line.getOptionValue(TwitterCorpusConstants.COMMANDLINE_ESCAPING);
		if(escaping == null){
			escaping = TwitterCorpusConstants.CONFIG_ESCAPING_ESC;
		}
		System.out.println("Escaping:\t" + escaping);
		
		// path
		String path = line.getOptionValue(TwitterCorpusConstants.COMMANDLINE_PATH);
		if(path == null){
			TwitterCorpus.usage(new HelpFormatter(), options, 1);
		}
		System.out.println("Path:\t\t" + path);
		
		// Start creating the corpus
		try {
			CreateTwitterCorpus createTwitterCorpus = new CreateTwitterCorpus(changefile,escaping,path,false);
			createTwitterCorpus.process();
			
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
		
	
	}
	
	
	private static void cmdCreateCorpusByQuery(Options options, CommandLine line) {
	    // Get the options needed for creating a corpus
	    System.out.println("Creating Corpus Files");
	    System.out.println("Options used:");
	    
	    // changefile
	    String changefile = line.getOptionValue(TwitterCorpusConstants.COMMANDLINE_CHANGEFILE);
	    if(changefile == null){
	        changefile = TwitterCorpusConstants.CONFIG_CHANGEFILE_HOURLY;
	    }
	    System.out.println("Changing file:\t" + changefile);
	    
	    // escaping
	    String escaping = line.getOptionValue(TwitterCorpusConstants.COMMANDLINE_ESCAPING);
	    if(escaping == null){
	        escaping = TwitterCorpusConstants.CONFIG_ESCAPING_ESC;
	    }
	    System.out.println("Escaping:\t" + escaping);
	    
	    // path
	    String path = line.getOptionValue(TwitterCorpusConstants.COMMANDLINE_PATH);
	    if(path == null){
	        TwitterCorpus.usage(new HelpFormatter(), options, 1);
	    }
	    System.out.println("Path:\t\t" + path);
	    
	    // path
	    String searchQuery = line.getOptionValue(TwitterCorpusConstants.COMMANDLINE_QUERY);
	    if(searchQuery == null){
	        TwitterCorpus.usage(new HelpFormatter(), options, 1);
	    }
	    System.out.println("Search Query:\t\t" + searchQuery);
	    
	    // Start creating the corpus
	    try {
	        CreateByQueryTwitterCorpus byQueryTwitterCorpus = new CreateByQueryTwitterCorpus(changefile, searchQuery, escaping, path, false);
	        byQueryTwitterCorpus.process();
	        
	    } catch (Exception e) {
	        e.printStackTrace();
	        System.exit(1);
	    }
	    
	    
	}
	
	
	private static void cmdStopCorpus(Options options, CommandLine line) {
		System.out.println("Stop creating Corpus Files");
		
		// path
		String path = line.getOptionValue(TwitterCorpusConstants.COMMANDLINE_PATH);
		if(path == null){
			TwitterCorpus.usage(new HelpFormatter(), options, 1);
		}
		System.out.println("Path:\t\t" + path);
		
		// Stop creating the corpus
		try {
			CreateTwitterCorpus createTwitterCorpus = new CreateTwitterCorpus(null,null,path,true);
			createTwitterCorpus.stopCorpusCreation();
			
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
	}

	
	private static void cmdValidateFiles(Options options, CommandLine line) {
		System.out.println("Validate files");
		
		// path
		String path = line.getOptionValue(TwitterCorpusConstants.COMMANDLINE_PATH);
		if(path == null){
			TwitterCorpus.usage(new HelpFormatter(), options, 1);
		}
		System.out.println("Path:\t\t" + path);
		
		// start validation
		try {
			Validator validator = new Validator(path);
			validator.process();
			
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
		
	}
	
	
	private static void cmdLanguageIdentification(Options options,
			CommandLine line) {
		
		System.out.println("Language identification");

		// mode
		// internal variable
		String mode = "textcat";
		
		// path
		String path = line.getOptionValue(TwitterCorpusConstants.COMMANDLINE_PATH);
		if(path == null){
			TwitterCorpus.usage(new HelpFormatter(), options, 1);
		}
		System.out.println("Path:\t\t" + path);
		// outputpath
		String outputpath = line.getOptionValue(TwitterCorpusConstants.COMMANDLINE_OUTPUTPATH);
		if(outputpath == null){
			TwitterCorpus.usage(new HelpFormatter(), options, 1);
		}
		System.out.println("OutputPath:\t\t" + outputpath);
		
		// start of language identification
		try {
			SaxFileReader saxFileReader = new SaxFileReader(path, outputpath, mode);
			saxFileReader.process();
			
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
			
		}
		
	}

	private static void cmdTagFiles(Options options, CommandLine line) {
		System.out.println("Tree Tagger");
		
		// taggerHome
		String taggerHome = line.getOptionValue(TwitterCorpusConstants.CONFIG_TAG_HOME);
		if(taggerHome == null){
			TwitterCorpus.usage(new HelpFormatter(), options, 1);
		}
		System.out.println("taggerHome:\t\t" + taggerHome);
		
		// modelPath
		String modelPath = line.getOptionValue(TwitterCorpusConstants.CONFIG_TAG_MODEL);
		if(modelPath == null){
			TwitterCorpus.usage(new HelpFormatter(), options, 1);
		}
		System.out.println("modelPath:\t\t" + modelPath);
		
		// path
		String path = line.getOptionValue(TwitterCorpusConstants.COMMANDLINE_PATH);
		if(path == null){
			TwitterCorpus.usage(new HelpFormatter(), options, 1);
		}
		System.out.println("Path:\t\t" + path);
		
		// outputpath
		String outputPath = line.getOptionValue(TwitterCorpusConstants.COMMANDLINE_OUTPUTPATH);
		if(outputPath == null){
			TwitterCorpus.usage(new HelpFormatter(), options, 1);
		}
		System.out.println("OutputPath:\t\t" + outputPath);
		
		try {
			TreeTagger treeTagger = new TreeTagger(taggerHome , modelPath , path , outputPath);
			
			treeTagger.process();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		
	}




	
}
